﻿#region Disclaimer / License
// Copyright (C) 2011, Kenneth Bergeron, IAP Worldwide Services, Inc
// NOAA :: National Marine Fisheries Service
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
// 
#endregion
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace CatchProcessing
{
    using LocalDataSet = DataSets.LocalDataSet;
    /// <summary>
    /// Enter catch
    /// </summary>
    public partial class CatchDialog : Form
    {
        /// <summary>
        /// The currently edited FishRow
        /// </summary>
        public LocalDataSet.FishRow Row { get; set; }
        /// <summary>
        /// Catch editor
        /// </summary>
        /// <param name="aRow">Row to edit</param>
        /// <param name="aAddNew">Is this a new row</param>
        public CatchDialog(LocalDataSet.FishRow aRow)
        {
            // Our edit row
            Row = aRow;
            InitializeComponent();
            // Strange thins happen at night in ToolStrips, the controls loose ther color, their visibility and Z-order
            this.SamplesToolStrip.Visible = true;
            this.SamplesDataGridView.BringToFront();
            this.OKAddToolStripButton.Visible = this.Row.RowState == DataRowState.Detached; // aAddNew;
            this.GoogleButton.Visible = Properties.Settings.Default.Google;
            this.onscreenKeyboardToolStripMenuItem.Click += new EventHandler(OnScreenKeyboard.OnScreenKeyboardToolStripMenuItem_Click);
            // Set up the 'levels' box.  Levels determine the Taxon set (recent, common, full)
            this.LevelComboBox.Items.AddRange(System.Enum.GetNames(typeof(Taxonomy.TaxonomyLevel)));
            CheckTags();
        }
        /// <summary>
        /// The form is loaded
        /// </summary>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            RestoreFormSize();
            if (Taxonomy.Loading)
            {
                // Wait for the loader to complete (maybe started earlier by Caller).
                Taxonomy.WaitForLoader();
            }
            if (!Taxonomy.Loaded) // Nothing has loaded the Tax, load it ourselves...
            {
                using (Utility.WaitDialog wd = new Utility.WaitDialog())
                {
                    wd.Show("Loading taxonomy database");
                    Taxonomy.LoadTax();
                    Taxonomy.WaitForLoader();
                }
            }
            // Load the Recent taxonomy form the database, done each time
            Taxonomy.LoadRecent((LocalDataSet.FishDataTable)Row.Table);
            // Sets all the controls from the Row
            Setup();
            // If there are no recents, use common.
            if (Taxonomy.Taxons[Taxonomy.TaxonomyLevel.Recent].Count == 0) Level = Taxonomy.TaxonomyLevel.Common;
            // Sets the Taxon combo lists
            SetCombo();
            // Set up the Samples datagridview
            RefreshSamplesTable();
            // Focus on the 
            this.TaxTextBox.Focus();
        }
        /// <summary>
        /// Restores form to saved size/state
        /// </summary>
        private void RestoreFormSize()
        {
            // If there is a size, location stored in settings, use it
            if (Properties.Settings.Default.IsCatchDialogWindowStateDefined &&
                Properties.Settings.Default.IsMainWindowStateDefined &&
                SystemInformation.VirtualScreen.Size == Properties.Settings.Default.MainWorkingArea)
            {
                this.WindowState = Properties.Settings.Default.CatchDialogFormWindowState;
                if (this.WindowState != FormWindowState.Maximized)
                {
                    this.Size = Properties.Settings.Default.CatchDialogWindowSize;
                    this.Location = Properties.Settings.Default.CatchDialogPosition;
                }
            }
        }
        /// <summary>
        /// Set the controls to the Row values
        /// </summary>
        private void Setup()
        {
            // Vessel in the caption
            this.Text = "Catch Processing " + Row.VesselName;
            this.txtCruise.Text = Row.Cruise;
            // Set the hook id
            this.HookIdTextBox.Text = Row.HookID.ToString();
            // And the station
            this.StationToolStripLabel.Text = Row.Station;
            // And that's all if in Chuck mode
            if (this.OKAddToolStripButton.Visible && !Properties.Settings.Default.AllowDefaults) return;

            // These null checks are not nessary - IU'm just superstisous
            if (Row.IsTRSNNull()) Row.TRSN = string.Empty;
            if (Row.IsSpeciesNull()) Row.Species = string.Empty;
            if (Row.IsWeightEstimatedNull()) Row.WeightEstimated = false;
            if (Row.IsWeightNull()) Row.Weight = 0d;
            if (Row.IsLengthEstimatedNull()) Row.LengthEstimated = false;
            if (Row.IsLenTotalNull()) Row.LenTotal = 0d;
            if (Row.IsLenForkNull()) Row.LenFork = 0d;
            if (Row.IsLenStdNull()) Row.LenStd = 0d;
            if (Row.IsCommentNull()) Row.Comment = string.Empty;
            // Set the taxonomy
            this.TaxTextBox.Text = Row.Species; // Taxonomy.GetTaxonomy(Row.TRSN);
            // Weight
            this.WeightEstCheckBox.Checked = Row.WeightEstimated;
            this.WeightNumericUpDown.Value = (decimal)Row.Weight;
            // Lengths
            this.LenExtCheckBox.Checked = Row.LengthEstimated;
            this.TotalNumericUpDown.Value = (decimal)Row.LenTotal;
            this.ForkNumericUpDown.Value = (decimal)Row.LenFork;
            this.StdNumericUpDown1.Value = (decimal)Row.LenStd;
            // Stage, sex, mortaility
            SetStage(Row.StageCode);
            SetSex(Row.SexCode);
            SetMortality(Row.MortalityCode);
            this.CommentTextBox.Text = Row.Comment;
            // Update the Samples gdv
            RefreshSamplesTable();
            // Set the tab control images
            MainTabControl_SelectedIndexChanged(this, null);
            // Focus on the Taxonomy
            this.TaxTextBox.Focus();
        }
        /// <summary>
        /// Reads the controls into a Row
        /// </summary>
        private void GetRow()
        {
            // The taxomomy stuff
            Row.TRSN = Taxonomy.Taxons[Taxonomy.TaxonomyLevel.Full].FindTRSN(this.TaxTextBox.Text);
            Row.Species = this.TaxTextBox.Text;
            // Weight
            Row.WeightEstimated = this.WeightEstCheckBox.Checked;
            Row.Weight = (double)this.WeightNumericUpDown.Value;
            //Lengths
            Row.LengthEstimated = this.LenExtCheckBox.Checked;
            Row.LenTotal = (double)this.TotalNumericUpDown.Value;
            Row.LenFork = (double)this.ForkNumericUpDown.Value;
            Row.LenStd = (double)this.StdNumericUpDown1.Value;
            // Stage, sex, mortality
            Row.StageCode = GetStage();
            Row.SexCode = GetSex();
            Row.MortalityCode = GetMortality();
            // Comment
            Row.Comment = this.CommentTextBox.Text;
        }
        /// <summary>
        /// Sets the Taxonomy drop-down
        /// </summary>
        private void SetCombo()
        {
            // Nothing changed...
            if (this.comboBox1.DataSource != null && this.comboBox1.DataSource.Equals(Taxonomy.Taxons[Level])) return;
            // Set the level
            this.LevelComboBox.SelectedItem = Level.ToString();
            // Save the Taxonomy
            string Was = this.TaxTextBox.Text;
            this.comboBox1.Suspend();       // Stops events
            this.comboBox1.DisplayMember = "Taxonomy";
            // Bind to the correct database
            this.comboBox1.DataSource = Taxonomy.Taxons[Level];
            this.comboBox1.UpdateDropDownWidth();
            // Position at the current text
            if (!string.IsNullOrEmpty(Was))
            {
                int ix = this.comboBox1.FindStringExact(Was);
                if (ix >= 0) this.comboBox1.SelectedIndex = ix;
            }
            this.comboBox1.Resume();        // resume events
        }
        /// <summary>
        /// The currently stored Taxonomy level
        /// </summary>
        private Taxonomy.TaxonomyLevel Level
        {
            get { return Properties.Settings.Default.Level; }
            set { Properties.Settings.Default.Level = value; Properties.Settings.Default.Save(); }
        }
        /// <summary>
        /// Changed the Level DropDown
        /// </summary>
        private void LevelButton_SelectionChangeCommited(object sender, EventArgs e)
        {
            Level = (Taxonomy.TaxonomyLevel)this.LevelComboBox.SelectedIndex;
            SetCombo();
        }
        /// <summary>
        /// Check controls validity
        /// </summary>
        /// <returns>True if all OK</returns>
        private bool Valid()
        {
            // Chuck mode = nodefaults and user must visit each control. (if new entry)
            bool ChuckMode = (this.OKAddToolStripButton.Visible &&            // new one
                    !Properties.Settings.Default.AllowDefaults);
            // Make sure user visited the taxonomy text or at least the group.
            if (ChuckMode && (string.IsNullOrEmpty(this.TaxTextBox.Text) || this.TaxGroupBox.Tag == null))
            {
                MessageBox.Show("Taxonomy must be selected.");
                return false;
            }
            // Make sure user visited length and weight
            if (ChuckMode && (this.LengthGroupBox.Tag == null || this.WeightGroupBox.Tag == null))
            {
                MessageBox.Show("Length and Weight must be selected.");
                return false;
            }
            // Make sure Mort, Sex and Stage were also visited
            if (ChuckMode &&
                (this.MortalityGroupBox.Tag == null ||
                this.SexGroupBox.Tag == null ||
                this.StageGroupBox.Tag == null))
            {
                MessageBox.Show("Mortality, Sex and Stage must be selected.");
                return false;
            }
            // Check Weight, Lengths
            if (this.WeightNumericUpDown.Value <= 0)
            {
                MessageBox.Show("A valid weight must be entered.");
                return false;
            }
            if (this.TotalNumericUpDown.Value == 0 && this.ForkNumericUpDown.Value == 0 && this.StdNumericUpDown1.Value == 0)
            {
                MessageBox.Show("A valid length must be entered.");
                return false;
            }
            if (string.IsNullOrEmpty(this.TaxTextBox.Text))
            {
                MessageBox.Show("A valid taxonomy must be selected.");
                return false;
            }
            if ((this.ForkNumericUpDown.Value != 0 && this.ForkNumericUpDown.Value > this.TotalNumericUpDown.Value) ||
                (this.StdNumericUpDown1.Value != 0 && this.StdNumericUpDown1.Value > this.TotalNumericUpDown.Value))
            {
                MessageBox.Show("Measurment inconsistancy: Fork or Standard is greater than total");
                return false;
            }
            return true;
        }
        /// <summary>
        /// Save all and exit
        /// </summary>
        private void Finish()
        {
            // Get the row values from the controls.
            GetRow();
            // And done.
            SaveForm();
            Close();
        }
        /// <summary>
        /// Pressed OK button
        /// </summary>
        private void OKButton_Click(object sender, EventArgs e)
        {
            // Check all is valid, if not, make user fix it.
            if (!Valid()) return;
            this.DialogResult = System.Windows.Forms.DialogResult.OK;
            Finish();
        }
        /// <summary>
        /// Pressed OkAdd
        /// </summary>
        /// <remarks>
        /// This is the same as the OK button except that RETRY is returned as the DialogResult
        /// Caller may use this to immediatly add a new row.
        /// </remarks>
        private void OkAddButton_Click(object sender, EventArgs e)
        {
            if (!Valid()) return;
            this.DialogResult = System.Windows.Forms.DialogResult.Retry;
            Finish();
        }
        /// <summary>
        /// Set Mortality radio buttons
        /// </summary>
        /// <param name="aCode">What to select</param>
        private void SetMortality(string aCode)
        {
            foreach (Control c in this.MortalityGroupBox.Controls)
                if (c is RadioButton)
                {
                    ((RadioButton)c).TabStop = false;
                    ((RadioButton)c).Checked = aCode == (string)c.Tag;
                }
        }
        /// <summary>
        /// Set Sex radio buttons
        /// </summary>
        /// <param name="aCode">What to select</param>
        private void SetSex(string aCode)
        {
            foreach (Control c in this.SexGroupBox.Controls)
                if (c is RadioButton)
                {
                    ((RadioButton)c).TabStop = false;
                    ((RadioButton)c).Checked = aCode == (string)c.Tag;
                }
        }
        /// <summary>
        /// Set Stage radio buttons
        /// </summary>
        /// <param name="aCode">What to select</param>
        private void SetStage(string aCode)
        {
            foreach (Control c in this.StageGroupBox.Controls)
                if (c is RadioButton)
                {
                    ((RadioButton)c).TabStop = false;
                    ((RadioButton)c).Checked = aCode == (string)c.Tag;
                }
        }
        /// <summary>
        /// Get selected Mortality code
        /// </summary>
        /// <returns>selected code</returns>
        private string GetMortality()
        {
            foreach (Control c in this.MortalityGroupBox.Controls)
                if (c is RadioButton && ((RadioButton)c).Checked) return c.Tag as string;
            return string.Empty;
        }
        /// <summary>
        /// Get selected Sex code
        /// </summary>
        /// <returns>selected code</returns>
        private string GetSex()
        {
            foreach (Control c in this.SexGroupBox.Controls)
                if (c is RadioButton && ((RadioButton)c).Checked) return c.Tag as string;
            return string.Empty;
        }
        /// <summary>
        /// Get selected Stage code
        /// </summary>
        /// <returns>selected code</returns>
        private string GetStage()
        {
            foreach (Control c in this.StageGroupBox.Controls)
                if (c is RadioButton && ((RadioButton)c).Checked) return c.Tag as string;
            return string.Empty;
        }
        /// <summary>
        /// Pressed Cancel
        /// </summary>
        private void CanToolStripButton_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            Close();
        }
        bool IsNew = false;
        bool ViewMode = false;
        /// <summary>
        /// This makes the form look different when a new row is being added.
        /// </summary>
        /// <param name="aNewOrNot">True if new row</param>
        private void SetNew(bool aNewOrNot)
        {
            IsNew = aNewOrNot;
            // Set the tool strip with a big fat label
            this.NewToolStripLabel.Text = aNewOrNot ? "N E W" : (ViewMode ? "V I E W" : "E D I T");
            // Now, green the thing up some.
            this.MainToolStrip.BackColor =
            this.TaxGroupBox.BackColor = 
                aNewOrNot ? Color.LawnGreen : this.WeightGroupBox.BackColor;
        }
        private void DisableForm()
        {
            this.TaxGroupBox.Enabled =
                this.WeightGroupBox.Enabled =
                this.LengthGroupBox.Enabled =
                this.MortalityGroupBox.Enabled =
                this.SexGroupBox.Enabled =
                this.StageGroupBox.Enabled =
                this.CommentGroupBox.Enabled =
                this.SamplesToolStrip.Enabled =
                    false;
        }
        /// <summary>
        /// Saves the form's state, size and location for next start
        /// </summary>
        private void SaveForm()
        {
            Properties.Settings.Default.CatchDialogWindowSize = this.Size;
            Properties.Settings.Default.CatchDialogFormWindowState = this.WindowState;
            Properties.Settings.Default.CatchDialogPosition = this.Location;
            Properties.Settings.Default.Save();
        }
        /// <summary>
        /// For reasons beyond all reason, one must set the TabStop of an exclusive radiobutton when it is selected.
        /// </summary>
        private void radioButton1_CheckedChanged(object sender, EventArgs e)
        {
            ((RadioButton)sender).TabStop = false;      // Only way this works
        }
        /// <summary>
        /// Add a Sample row and edit it using the dialog.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SampleAddToolStripButton_Click(object sender, EventArgs e)
        {
            DataSets.LocalDataSet.FishSamplesRow NewRow = this.Row.NewFishSamplesRow();
            if (CurrentFishSamplesRow != null)
            {
                int ItemNo = NewRow.Index;
                NewRow.ItemArray = CurrentFishSamplesRow.ItemArray; // Current one is default;
                NewRow.Index = ItemNo;
            }
            SampleDialog sd = new SampleDialog(Row);
            if (sd.ShowDialog(NewRow, false) == System.Windows.Forms.DialogResult.OK)
                this.Row.AddFishSamplesRow(NewRow);
            RefreshSamplesTable();
        }
        /// <summary>
        /// Shortcut to get the current datagridview row
        /// </summary>
        private DataSets.LocalDataSet.FishSamplesRow CurrentFishSamplesRow
        {
            get 
            {
                if (this.SamplesDataGridView.CurrentRow == null) return null;
                return RowAt(this.SamplesDataGridView.CurrentRow.Index);
            }
        }
        /// <summary>
        /// Edit a Samples row
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SampleEditToolStripButton_Click(object sender, EventArgs e)
        {
            if (this.SamplesDataGridView.CurrentRow == null) return;
            DataSets.LocalDataSet.FishSamplesRow eRow = CurrentFishSamplesRow;
            SampleDialog sd = new SampleDialog(Row);
            if (!this.ViewMode) sd.ShowDialog(eRow, true);
            else sd.ViewDialog(eRow); // Only look
            RefreshSamplesTable();
        }
        /// <summary>
        /// You guessed it: the binding source for the Samples DataGridView
        /// </summary>
        private BindingSource SamplesBindingSource = new BindingSource();
        /// <summary>
        /// Refresh all entries in the Samples DataGridView
        /// </summary>
        private void RefreshSamplesTable()
        {
            // Whoa
            this.SamplesBindingSource.SuspendBinding();
            // It's read only
            this.SamplesBindingSource.AllowNew = false;
            // Don't do that.
            this.SamplesDataGridView.AutoGenerateColumns = false;
            // Get the Rows from the Database
            DataSets.LocalDataSet.FishSamplesRow[] R = this.Row.GetFishSamplesRows();
            // Sort the rows by Type (Length, Sample or Tag) and bind
            this.SamplesBindingSource.DataSource = R.OrderBy(qR=>qR.Type).ToArray();
            // Set the DataSource and redraw
            this.SamplesDataGridView.DataSource = this.SamplesBindingSource;
            this.SamplesBindingSource.ResumeBinding();
            this.SamplesDataGridView.Refresh();
        }
        /// <summary>
        /// Pressed Delete, Remove a Sample
        /// </summary>
        private void SampleDelButton_Click(object sender, EventArgs e)
        {
            if (this.SamplesDataGridView.SelectedRows.Count == 0) return;
            if (MessageBox.Show("Delete selected row?", "DELETE", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.No) return;
            DataSets.LocalDataSet.FishSamplesRow eRow =  CurrentFishSamplesRow;
            eRow.Delete();
            RefreshSamplesTable();
        }
        /// <summary>
        /// Any time a group is Entered, this guy sets the groupBox Tag.
        /// </summary>
        /// <remarks>
        /// This is used to see if the group box was entered by the user (for Chuck mode).
        /// </remarks>
        private void GroupBox_Enter(object sender, EventArgs e)
        {
            ((GroupBox)sender).Tag = true;
        }
        /// <summary>
        /// A shortcut to Settings: set the values
        /// </summary>
        private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
        {
            this.allowDefaultsToolStripMenuItem.Checked = Properties.Settings.Default.AllowDefaults;
            this.googleToolStripMenuItem.Checked = Properties.Settings.Default.Google;
        }
        /// <summary>
        /// Shortcut to Settings: Save the selections
        /// </summary>
        private void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            // Do not use AutoCheck
            ((ToolStripMenuItem)e.ClickedItem).Checked = !((ToolStripMenuItem)e.ClickedItem).Checked;
            Properties.Settings.Default.AllowDefaults = this.allowDefaultsToolStripMenuItem.Checked;
            Properties.Settings.Default.Google = this.googleToolStripMenuItem.Checked;
            Properties.Settings.Default.Save();
            this.GoogleButton.Visible = Properties.Settings.Default.Google;
        }
        /// <summary>
        /// Tool Strip double-clicked - Set sane size
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStrip1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.WindowState = FormWindowState.Normal;
            this.Size = new Size(640, 480);
        }
        /// <summary>
        /// After user leaves the Taxonomy box, unset the newness
        /// </summary>
        private void TaxGroupBox_Leave(object sender, EventArgs e)
        {
            if (IsNew) SetNew(false);
        }
        /// <summary>
        /// A handy override of ShowDialog that set the newness
        /// </summary>
        public DialogResult ShowDialog(bool aNew)
        {
            this.ViewMode = false;
            SetNew(aNew);
            return ShowDialog();
        }
        /// <summary>
        /// A handy override of ShowDialog that shows the form read-only
        /// </summary>
        public DialogResult ViewDialog()
        {
            this.ViewMode = true;
            SetNew(false);
            this.OKButton.Visible = false;
            this.CanToolStripButton.Text = "OK";
            DisableForm();
            return ShowDialog();
        }
        /// <summary>
        /// DGV double-clicked, shortcut to edit
        /// </summary>
        private void LengthDataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            SampleEditToolStripButton_Click(sender, null);
        }
        /// <summary>
        /// Handy tool to get the DataRow at a DGV Row
        /// </summary>
        private DataSets.LocalDataSet.FishSamplesRow RowAt(int aRowIndex)
        {
            // if index is goofy, return
            if (aRowIndex > this.SamplesDataGridView.Rows.Count || aRowIndex < 0) return null;
            // If we have adirect bind, just return the DataBoundItem
            if (this.SamplesDataGridView.Rows[aRowIndex].DataBoundItem is DataSets.LocalDataSet.FishSamplesRow)
                return (DataSets.LocalDataSet.FishSamplesRow) this.SamplesDataGridView.Rows[aRowIndex].DataBoundItem;
            // Else, assume that the DataBoundItem is a DataRowView
            return (DataSets.LocalDataSet.FishSamplesRow)((DataRowView)this.SamplesDataGridView.Rows[aRowIndex].DataBoundItem).Row;
        }
        /// <summary>
        /// Format the DataGridView cells
        /// </summary>
        /// <param name="e">Has the indexes, value and FormattedFlag</param>
        private void SamplesDataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            // In one of the headers, just return
            if (e.RowIndex < 0 || e.ColumnIndex < 0) return;
            // The description of the sample
            if (e.ColumnIndex == this.CodeNameCol.Index)
            {
                e.Value = DataSets.Glob.Support.Describe(RowAt(e.RowIndex).Type, (string)e.Value);
                e.FormattingApplied = true;
            }
            // The value is Row.Identifier if the sample is a Tag
            else if (e.ColumnIndex == this.ValueCol.Index)
            {
                if (RowAt(e.RowIndex).Sample == DataSets.LocalDataSet.FishSamplesRow.SampleType.Tag)
                {
                    e.Value = string.Empty;
                    e.FormattingApplied = true;
                }
            }
            else if (e.ColumnIndex == this.NumberCol.Index)
            {
                if (RowAt(e.RowIndex).Sample == DataSets.LocalDataSet.FishSamplesRow.SampleType.Tag)
                    e.Value = RowAt(e.RowIndex).Identifier;
                else
                    e.Value = string.Empty;
                e.FormattingApplied = true;
            }
            else if (e.ColumnIndex == this.descriptionDataGridViewTextBoxColumn.Index)
            {
                List<string> Desc = new List<string>();
                if (!string.IsNullOrEmpty( RowAt(e.RowIndex).Description ))
                    Desc.Add(RowAt(e.RowIndex).Description);
                if (RowAt(e.RowIndex).Sample != DataSets.LocalDataSet.FishSamplesRow.SampleType.Tag
                    && !string.IsNullOrEmpty(RowAt(e.RowIndex).Identifier))
                    Desc.Add( RowAt(e.RowIndex).Identifier);
                if (!string.IsNullOrEmpty(RowAt(e.RowIndex).Comment))
                    Desc.Add(RowAt(e.RowIndex).Comment);
                e.Value = Desc.Count == 0 ? "" : string.Join(":",Desc.ToArray());
                e.FormattingApplied = true;
            }
            if (e.Value is double && e.Value != null && (double)e.Value == 0d)
            {
                e.Value = string.Empty;
                e.FormattingApplied = true;
            }
        }
        /// <summary>
        /// Google button pressed, Google the Taxonomy value
        /// </summary>
        private void GoogleClick(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("http://www.google.com/search?q=" + this.TaxTextBox.Text);
        }
        /// <summary>
        /// Tab was changed, update the tab control tab labels
        /// </summary>
        private void MainTabControl_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.CommentTabPage.ImageIndex = string.IsNullOrEmpty(this.CommentTextBox.Text) ? 0 : 1;
            this.SamplesTabPage.ImageIndex = this.SamplesDataGridView.RowCount == 0 ? 0 : 1;
            this.CatchTabPage.ImageIndex = 1;
        }
        /// <summary>
        /// The help screen is a browser window
        /// </summary>
        private Helper HelpScreen = null;
        /// <summary>
        /// Put up help
        /// </summary>
        /// <param name="aDoc">HTML File</param>
        public void ShowHelp(string aDoc)
        {
            // If 1st time, create the screen
            if (this.HelpScreen == null || this.HelpScreen.IsDisposed)
                this.HelpScreen =
                    new Helper(System.IO.Path.Combine(Application.StartupPath, "Docs", aDoc));
            // Assure visible
            this.HelpScreen.Show();
            this.HelpScreen.WindowState = FormWindowState.Normal;
            this.HelpScreen.BringToFront();
        }
        /// <summary>
        /// Help pressed (not aboout)
        /// </summary>
        private void helpToolStripButton_Click(object sender, EventArgs e)
        {
            ShowHelp("CatchEntry.htm");
        }
        /// <summary>
        /// Each NUD has a buddy text box, introduce them
        /// </summary>
        private void CheckTags()
        {
            if (this.ForkNumericUpDown.Tag != null) return;
            this.ForkNumericUpDown.Tag = this.ForkTextBox;
            this.ForkTextBox.Tag = this.ForkNumericUpDown;
            this.StdNumericUpDown1.Tag = this.StdTextBox;
            this.StdTextBox.Tag = this.StdNumericUpDown1;
            this.TotalNumericUpDown.Tag = this.TotTextBox;
            this.TotTextBox.Tag = this.TotalNumericUpDown;
        }
        /// <summary>
        /// When the value changes on one of the Length NUD's, set the value of its buddy
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LenNumericUpDown_ValueChanged(object sender, EventArgs e)
        {
            NumericUpDown nud = (NumericUpDown)sender;
            TextBox tb = (TextBox)nud.Tag;
            decimal mtval;
            if (!decimal.TryParse(tb.Text, out mtval) || mtval != nud.Value)
                tb.Text = nud.Value.ToString("N" + nud.DecimalPlaces.ToString());
        }
        /// <summary>
        /// When typing into a Buddy textbox, do not allow characters and set the NUD's value
        /// </summary>
        private void ForkTextBox_KeyUp(object sender, KeyEventArgs e)
        {
            TextBox tb = (TextBox)sender;
            NumericUpDown nud = (NumericUpDown)tb.Tag;
            string Text = tb.Text;
            if (string.IsNullOrEmpty(tb.Text)) Text = "0";
            decimal Poot;
            if (!decimal.TryParse(tb.Text, out Poot))
            {
                System.Media.SystemSounds.Beep.Play();
                tb.Text = Text.Substring(0, Text.Length - 1);
                tb.SelectionStart = Text.Length-1;
            }
            else if (nud.Value != Poot)
            {
                nud.Value = Poot;
            }
        }
        /// <summary>
        /// Leave a NUD or buddy TextBox, then blank if zero
        /// </summary>
        private void ForkTextBox_Leave(object sender, EventArgs e)
        {
            TextBox tb = (TextBox)((sender is NumericUpDown) ? ((NumericUpDown)sender).Tag : sender);
            decimal Poot;
            if (!decimal.TryParse(tb.Text, out Poot) || Poot == 0)
                tb.Text = string.Empty;
        }

        private void SettingsToolStripButton_Click(object sender, EventArgs e)
        {
            this.contextMenuStrip1.Show(System.Windows.Forms.Control.MousePosition);
        }
    }
}
